package org.woldier.hadoop.service.impl;


import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.fs.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.woldier.hadoop.config.HadoopHDFSConfig;
import org.woldier.hadoop.service.HdfsService;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class HdfsServiceImpl implements HdfsService {

    // 全局变量定义
    private static final int bufferSize = 1024 * 1024 * 64;


    // 日志记录服务
    private static final Logger logger = LoggerFactory.getLogger(HdfsServiceImpl.class);

    @Autowired
    private FileSystem fileSystem;

    @Autowired
    private HadoopHDFSConfig hadoopHDFSConfig;

    /**
     * HDFS 文件夹创建
     * @param path
     * @return
     */
    @Override
    public boolean mkdirFolder(String path) {
// TODO Auto-generated method stub
        boolean target = false;
        if (StringUtils.isEmpty(path)) {
            return false;
        }
        if (existFile(path)) {
            return true;
        }
        Path src = new Path(path);
        try {
            target = fileSystem.mkdirs(src);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        }
        return target;
    }

    @Override
    public boolean existFile(String path) {
        // TODO Auto-generated method stub
        boolean target = false;

        if (StringUtils.isEmpty(path)) {
            return target;
        }
        Path src = new Path(path);
        try {
            target = fileSystem.exists(src);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        }
        return target;
    }


    /**
     * HDFS 读取目录信息 只找当前目录下的文件核文件夹 不会进入文件夹遍历
     * @param path
     * @return
     */
    @Override
    public List<Map<String, Object>> readCatalog(String path) {
        // TODO Auto-generated method stub
        if (StringUtils.isEmpty(path)) {
            return null;
        }
        if (!existFile(path)) {
            return null;
        }

        // 目标路径
        Path newPath = new Path(path);
        FileStatus[] statusList = null;
        try {
            statusList = fileSystem.listStatus(newPath);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        }
        List<Map<String, Object>> list = new ArrayList<>();
        if (null != statusList && statusList.length > 0) {
            for (FileStatus fileStatus : statusList) {
                Map<String, Object> map = new HashMap<>();
                map.put("filePath", fileStatus.getPath());
                map.put("fileStatus", fileStatus.toString());
                list.add(map);
            }
            return list;
        } else {
            return null;
        }

    }

    @Override
    public void createFile(String path, MultipartFile file) {

    }

    /**
     * HDFS 读完文件列表
     * @param path
     * @return
     */
    @Override
    public String readFileContent(String path) {
      return null;
    }

    /**
     * HDFS 读完文件列表
     * @param path
     * @return
     */
    @Override
    public List<Map<String, String>> listFile(String path) {
        // TODO Auto-generated method stub
        List<Map<String, String>> returnList = new ArrayList<>();
        if (StringUtils.isEmpty(path)) {
            return null;
        }
        if (!existFile(path)) {
            return null;
        }
        // 目标路径
        Path srcPath = new Path(path);
        // 递归找到所有文件
        try{
            RemoteIterator<LocatedFileStatus> filesList = fileSystem.listFiles(srcPath, true);
            while (filesList.hasNext()) {
                LocatedFileStatus next = filesList.next();
                String fileName = next.getPath().getName();
                Path filePath = next.getPath();
                Map<String, String> map = new HashMap<>();
                map.put("fileName", fileName);
                map.put("filePath", filePath.toString());
                returnList.add(map);
            }
        }catch(Exception e){
            logger.error(e.getMessage());
        }
        return returnList;

    }

    @Override
    public boolean renameFile(String oldName, String newName) {
        // TODO Auto-generated method stub
        boolean target = false;
        if (StringUtils.isEmpty(oldName) || StringUtils.isEmpty(newName)) {
            return false;
        }
        // 原文件目标路径
        Path oldPath = new Path(oldName);
        // 重命名目标路径
        Path newPath = new Path(newName);
        try{
            target = fileSystem.rename(oldPath, newPath);
        }catch(Exception e){
            logger.error(e.getMessage());
        }

        return target;
    }

    @Override
    public boolean deleteFile(String path) {
        // TODO Auto-generated method stub
        boolean target = false;
        if (StringUtils.isEmpty(path)) {
            return false;
        }
        if (!existFile(path)) {
            return false;
        }
        Path srcPath = new Path(path);
        try{
            target = fileSystem.delete(srcPath);
        }catch(Exception e){
            logger.error(e.getMessage());
        }

        return target;
    }


    /**
     * 上传失败的逻辑需要完善
     * @param path
     * @param uploadPath
     */
    @Override
    public void uploadFile(String path, String uploadPath) {
        // TODO Auto-generated method stub
        if (StringUtils.isEmpty(path) || StringUtils.isEmpty(uploadPath)) {
            return;
        }
        // 上传路径
        Path clientPath = new Path(path);
        // 目标路径
        /**
         * 此处的uid 到时候换位用户id 以便做不同用户的区分
         * */
        uploadPath =  "uid"+uploadPath;
        Path serverPath = new Path(uploadPath);

        // 调用文件系统的文件复制方法，第一个参数是否删除原文件true为删除，默认为false
        try {
            fileSystem.copyFromLocalFile(false, clientPath, serverPath);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        }
    }


    /**
     *
     * 下载失败的逻辑出路还需要完善
     * @param path
     * @param downloadPath
     */
    @Override
    public void downloadFile(String path, String downloadPath) {
// TODO Auto-generated method stub
        if (StringUtils.isEmpty(path) || StringUtils.isEmpty(downloadPath)) {
            return;
        }
        // 上传路径
        path =  "uid"+path;
        Path clientPath = new Path(path);
        // 目标路径
        /**
         * 此处的uid 到时候换位用户id 以便做不同用户的区分
         * */

        Path serverPath = new Path(downloadPath);

        // 调用文件系统的文件复制方法，第一个参数是否删除原文件true为删除，默认为false
        try {
            fileSystem.copyToLocalFile(false, clientPath, serverPath);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage());
        }

    }

    @Override
    public void copyFile(String sourcePath, String targetPath) {

    }

    @Override
    public byte[] openFileToBytes(String path) {
        return new byte[0];
    }

    @Override
    public BlockLocation[] getFileBlockLocations(String path) {
        return new BlockLocation[0];
    }
}
